package com.md.api.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.md.api.common.utils.*;
import com.md.api.dao.*;
import com.md.api.entity.*;
import com.md.api.entity.enums.UserStatus;
import com.md.api.entity.enums.VipStatus;
import com.md.api.entity.ftp.*;
import com.md.api.entity.util.OssPage;
import com.md.api.service.UserSevice;
import com.md.api.common.config.RedisKeys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @Author liujie
 * @ClassName UserServiceImpl
 **/

@Slf4j
@Service
public class UserServiceImpl implements UserSevice {

    @Resource
    TbOrderVirtuallyMapper storageMapper;
    @Resource
    RedisUtil redisUtil;
    @Resource
    UserMapper userMapper;
    @Resource
    TokenUtil tokenUtil;
    @Resource
    VipPropertiesMapper vipMapper;
    @Resource
    UserVipMapper userVipMapper;
    @Resource
    UserFtpMapper ftpMapper;
    @Value("${common-key}")
    String commonKey;
    @Value("${ftp-host}")
    String ftpHost;
    @Value("${ftp-port}")
    String ftpPort;
    @Value("${ftp-web-port}")
    String ftpWebPort;


    @Override
    public HttpResult getInfo(HttpServletRequest request) {
        String language = request.getHeader("language");
        String userId = tokenUtil.getUserId(request);
        UserInfo dbuser = userMapper.getByUserId(userId);
        if (null==dbuser){
            if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                return HttpResult.fail("Account does not exist");
            }
            return HttpResult.fail("賬號不存在！");
        }
        if (null!=dbuser.getUseStorage()&&dbuser.getUseStorage()>0){
            BigDecimal num1 = new BigDecimal(dbuser.getUseStorage());
            BigDecimal num2 = new BigDecimal(1024*1024*1024);
            dbuser.setUseStorage(num1.divide(num2,2, RoundingMode.HALF_UP).doubleValue());
        }
        dbuser.setStorage(storageMapper.getTotalEffectiveStorage(dbuser.getUserId()));
        dbuser.setCurrentVip(userVipMapper.getCurrentVip(dbuser.getUserId()));
        UserFtp ftpUser = ftpMapper.getByUserId(dbuser.getUserId());
        if (null!=ftpUser) {
            ftpUser.setFtpHost(ftpHost);
            ftpUser.setFtpPort(ftpPort);
            ftpUser.setPassword(AESUtil.encrypt(ftpUser.getPassword(),commonKey));
            dbuser.setFtpUser(ftpUser);
        }
        String token = request.getHeader("token");
        dbuser.setToken(token);
        redisUtil.set(RedisKeys.getUserTokenInfoKey(token),dbuser,3600*24);
        return new HttpResult(dbuser);
    }

    @Override
    public HttpResult register(HttpServletRequest request,  UserInfo user) {
        try {
            String code;
            String language = request.getHeader("language");
            // 查看是否有缓存
            code = redisUtil.getString(RedisKeys.SMS_CODE.redisKey()  + user.getEmail());
            if(VerifyUtil.isMiss(code)){
                if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                    return HttpResult.fail("The verification code has expired");
                }
                return HttpResult.fail("驗證碼已過期!");
            }
            if(!code.equalsIgnoreCase(user.getMessageCode())){
                if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                    return HttpResult.fail("The verification code is error");
                }
                return HttpResult.fail("驗證碼錯誤!");
            }
            UserInfo dbUserPhone = userMapper.findByPhone(user.getPhone());
            if (dbUserPhone!=null&&dbUserPhone.getStatus()==UserStatus.LOG_OFF.value()){
                userMapper.updateStatus(dbUserPhone.getUserId(),UserStatus.NORMAL.value());
                return HttpResult.OK;
            }
            if (dbUserPhone!=null&&dbUserPhone.getStatus()!=UserStatus.LOG_OFF.value()){
                if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                    return HttpResult.fail("The phone number is already in use");
                }
                return HttpResult.fail("該手機號已被使用！");
            }
            UserInfo dbUserEmail = userMapper.findByEmail(user.getEmail());
            if (dbUserEmail!=null&&dbUserEmail.getStatus()==UserStatus.LOG_OFF.value()){
                userMapper.updateStatus(dbUserEmail.getUserId(),UserStatus.NORMAL.value());
                return HttpResult.OK;
            }
            if (dbUserEmail!=null&&dbUserEmail.getStatus()!=UserStatus.LOG_OFF.value()){
                if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                    return HttpResult.fail("This email is already in use");
                }
                return HttpResult.fail("該郵箱已被使用！");
            }
            String userId = Md5Utils.encode(user.getEmail());
            user.setUserId(userId);
            if(StringUtils.isEmpty(user.getNickName())){
                user.setNickName(user.getEmail());
            }

            //赠送免费次数
            List<VipProperties> freeServices = vipMapper.getFreeService();
            VipProperties freeService = freeServices.stream().max(Comparator.comparing(VipProperties::getWeight)).get();
            if (null!=freeService){
                //初始创建会员购买
                UserVip userVip = new UserVip();
                userVip.setCurrentPrice(freeService.getCurrentPrice());
                userVip.setPrice(freeService.getPrice());
                userVip.setServiceCode(freeService.getServiceCode());
                userVip.setServiceName(freeService.getServiceName());
                userVip.setIsFacialRecognition(freeService.getIsFacialRecognition());
                userVip.setIsCompression(freeService.getIsCompression());
                userVip.setServiceDate(freeService.getServiceDate());
                userVip.setDateType(freeService.getDateType());
                if (freeService.getDateType()==1){
                    userVip.setTotalDay(365*freeService.getServiceDate());
                }else if (freeService.getDateType()==2){
                    userVip.setTotalDay(30*freeService.getServiceDate());
                }else if (freeService.getDateType()==5){
                    userVip.setTotalDay(freeService.getServiceDate());
                }
                userVip.setDownloadTypes(freeService.getDownloadTypes());
                userVip.setIsFtp(freeService.getIsFtp());
                userVip.setIsFree(freeService.getIsFree());
                userVip.setIsOnline(freeService.getIsOnline());
                userVip.setIsSecretVisit(freeService.getIsSecretVisit());
                userVip.setIsHighSecret(freeService.getIsHighSecret());
                userVip.setIsPoster(freeService.getIsPoster());
                userVip.setAiTimes(freeService.getAiTimes());
                userVip.setSurplusAiTimes(freeService.getAiTimes());
                userVip.setStorage(freeService.getStorage());
                userVip.setIsVideo(freeService.getIsVideo());
                userVip.setIsLogo(freeService.getIsLogo());
                userVip.setWeight(freeService.getWeight());
                userVip.setUserId(userId);
                userVip.setStatus(VipStatus.IN_EFFECT.value());
                userVip.setEffectiveTime(new Date());
                userVip.setPurchaseTime(new Date());
                userVip.setExpiredTime(DateUtils.add(new Date(), freeService.getDateType(),freeService.getServiceDate()));
                userVipMapper.insert(userVip);
                //初始次数和内存
//                user.setAiTimes(freeService.getAiTimes());
//                user.setUseStorage(freeService.getStorage());

            }
            userMapper.register(user);
        }catch (Exception e){
            e.printStackTrace();
            return HttpResult.fail("注冊失敗！");
        }
        return HttpResult.OK;
    }

    @Override
    public HttpResult updateBaseInfo(HttpServletRequest request, UserInfo user) {
        String userId = tokenUtil.getUserId(request);
        if (StringUtils.isNotEmpty(user.getPhone())){
            //校验电话是否重复
            int count = userMapper.checkPhone(userId,user.getPhone());
            if (count>0){
                return HttpResult.fail("該電話已被使用!");
            }
        }
        user.setUserId(userId);
        userMapper.updateBase(user);
        UserInfo dbuser = userMapper.getByUserId(userId);
        String token = request.getHeader("token");
        dbuser.setToken(token);
        redisUtil.set(RedisKeys.getUserTokenInfoKey(token),dbuser,3600*24);
        return new HttpResult(dbuser);
    }

    @Override
    public HttpResult userLogin(HttpServletRequest request, UserInfo user) {
        try {
            String code;
            String language = request.getHeader("language");
            // 查看是否有缓存
            code = redisUtil.getString(RedisKeys.SMS_CODE.redisKey()  + user.getUserName());
            if(VerifyUtil.isMiss(code)){
                if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                    return HttpResult.fail("The verification code has expired");
                }
                return HttpResult.fail("驗證碼已過期!");
            }
            if(!code.equalsIgnoreCase(user.getMessageCode())){
                if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                    return HttpResult.fail("The verification code is error");
                }
                return HttpResult.fail("驗證碼錯誤!");
            }
            UserInfo dbuser = null;
            Pattern EMAIL_PATTERN = Pattern.compile(
                            "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
                                    "\\@" +
                                    "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
                                    "(" +
                                    "\\." +
                                    "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
                                    ")+"
                    );
            boolean isEmail = EMAIL_PATTERN.matcher(user.getUserName()).matches();
            if (isEmail){
                dbuser = userMapper.loginByEmail(user.getUserName());
                if (null==dbuser){
                    if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                        return HttpResult.fail("Account does not exist");
                    }
                    return HttpResult.fail("賬號不存在！");
                }
            }else{
                dbuser = userMapper.loginByPhone(user.getUserName());
                if (null==dbuser){
                    if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                        return HttpResult.fail("Account does not exist");
                    }
                    return HttpResult.fail("賬號不存在！");
                }
            }
            if (null!=dbuser.getUseStorage()&&dbuser.getUseStorage()>0){
                BigDecimal num1 = new BigDecimal(dbuser.getUseStorage());
                BigDecimal num2 = new BigDecimal(1024*1024*1024);
                dbuser.setUseStorage(num1.divide(num2,2, RoundingMode.HALF_UP).doubleValue());
            }
            dbuser.setStorage(storageMapper.getTotalEffectiveStorage(dbuser.getUserId()));
            dbuser.setCurrentVip(userVipMapper.getCurrentVip(dbuser.getUserId()));
            UserFtp ftpUser = ftpMapper.getByUserId(dbuser.getUserId());
            if (null!=ftpUser) {
                ftpUser.setFtpHost(ftpHost);
                ftpUser.setFtpPort(ftpPort);
                dbuser.setFtpUser(ftpUser);
            }
            String loginToken = UUID.randomUUID().toString().replaceAll("-", "");
            dbuser.setToken(loginToken);
            redisUtil.set(RedisKeys.getUserTokenInfoKey(loginToken),dbuser,3600*24);
            return new HttpResult(dbuser);
        }catch (Exception e){
            e.printStackTrace();
            return HttpResult.fail("登錄失敗！");
        }
    }

    @Override
    public HttpResult loginOut(HttpServletRequest request) {

        redisUtil.removeKey(RedisKeys.getUserTokenInfoKey(request.getHeader("token")));
        return HttpResult.OK;
    }

    @Override
    public HttpResult logOff(HttpServletRequest request) {

        redisUtil.removeKey(RedisKeys.getUserTokenInfoKey(request.getHeader("token")));
        String userId = tokenUtil.getUserId(request);
        userMapper.updateStatus(userId, UserStatus.LOG_OFF.value());
        //清空ftp账号及照片


        //清空相册


        return HttpResult.OK;
    }
    @Override
    public HttpResult registerFtp(HttpServletRequest request, UserFtp ftp) {
        String userId = tokenUtil.getUserId(request);
        String language = request.getHeader("language");
        UserInfo userInfo = tokenUtil.getUserInfo(request);
        UserVip currentVip = userInfo.getCurrentVip();
        if (null==currentVip||currentVip.getIsFtp()!=1){
            if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                return HttpResult.fail("No FTP permissions currently available");
            }
            return HttpResult.fail("暫無ftp權限！");
        }
        ftp.setUserId(userId);
        UserFtp dnftp = ftpMapper.getByUserName(ftp.getUserName());
        if (dnftp!=null){
            if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                return HttpResult.fail("This account has been used");
            }
            return HttpResult.fail("該賬號已被使用！");
        }
        String homeDir =AliOssUtil.CUSTOM+userId+"/ftp/";
        AliOssUtil.createFolder(homeDir);
        ftp.setHomeDir(homeDir);
        ftp.setBucketName(AliOssUtil.bucketName);
        String password =AESUtil.decrypt(ftp.getPassword(),commonKey);
        ftp.setPassword(password);
        ftpMapper.insert(ftp);
        //异步创建ftp账号
        Account newAccount = new Account();
        newAccount.setAccess_id(AliOssUtil.accessKeyId);
        newAccount.setAccess_secret(AliOssUtil.accessKeySecret);
        newAccount.setBucket_name(AliOssUtil.bucketName);
        newAccount.setHome_dir(homeDir);
        newAccount.setLogin_username(ftp.getUserName());
        newAccount.setLogin_password(password);
        addUserToFtpFile(newAccount);
        ftp.setFtpHost(ftpHost);
        ftp.setFtpPort(ftpPort);
        return new HttpResult(ftp);
    }



    @Async
    public synchronized HttpResult addUserToFtpFile(Account newAccount) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            // 读取JSON文件
            String jsonStr = new String(Files.readAllBytes(Paths.get("/data/ossftp/config.json")));
            FtpFileInfo fileInfo = mapper.readValue(jsonStr, FtpFileInfo.class);
            System.out.println("读取json文件内容：" + JsonUtils.toJsonString(fileInfo));
            Modules modules = fileInfo.getModules();
            Ossftp ossftp = modules.getOssftp();
            ossftp.setAddress("0.0.0.0");
            ossftp.setPort(2048);
            ossftp.setPassive_ports_start(51000);
            ossftp.setPassive_ports_end(53000);
            ossftp.setLog_level("INFO");
            ossftp.setBucket_endpoints("photo-oss-file.oss-cn-shanghai.aliyuncs.com");
            List<Account> accounts = modules.getAccounts();
            accounts.add(newAccount);
            // 写入JSON文件
            String jsonContent = mapper.writeValueAsString(fileInfo);
            Files.write(Paths.get("/data/ossftp/config.json"), jsonContent.getBytes(), StandardOpenOption.CREATE);

            //重启服务f
            HttpUtil.doGet("http://"+ftpHost+":"+ftpWebPort+"/restart");
            return HttpResult.fail("resetFtpFile success");
        } catch (Exception e) {
            e.printStackTrace();
            return HttpResult.fail("resetFtpFile failed");
        }
    }

    @Override
    public void resetFtpFile() {
        try {
            ObjectMapper mapper = new ObjectMapper();
            // 读取JSON文件
            String jsonStr = new String(Files.readAllBytes(Paths.get("/data/ossftp/config.json")));
            FtpFileInfo fileInfo = mapper.readValue(jsonStr, FtpFileInfo.class);
            System.out.println("读取json文件内容：" + JsonUtils.toJsonString(fileInfo));
            Modules modules = fileInfo.getModules();
            Launcher launcher = modules.getLauncher();
            launcher.setAuto_start(0);
            launcher.setControl_port(8192);
            launcher.setPopup_webui(1);
            launcher.setShow_systray(1);
            launcher.setLanguage("cn");
            Ossftp ossftp = modules.getOssftp();
            ossftp.setAddress("0.0.0.0");
            ossftp.setPort(2048);
            ossftp.setPassive_ports_start(51000);
            ossftp.setPassive_ports_end(53000);
            ossftp.setLog_level("INFO");
            ossftp.setBucket_endpoints("photo-oss-file.oss-cn-shanghai.aliyuncs.com");
            List<Account> accounts = new ArrayList<>();
            List<UserFtp> users = ftpMapper.selectAllEnableUser();
            for (UserFtp u :users){
                Account newAccount = new Account();
                newAccount.setAccess_id(AliOssUtil.accessKeyId);
                newAccount.setAccess_secret(AliOssUtil.accessKeySecret);
                newAccount.setBucket_name(AliOssUtil.bucketName);
                String homeDir =AliOssUtil.CUSTOM+u.getUserId()+"/ftp/";
                newAccount.setHome_dir(homeDir);
                newAccount.setLogin_password(u.getPassword());
                newAccount.setLogin_username(u.getUserName());
                accounts.add(newAccount);
            }
            modules.setAccounts(accounts);
            // 写入JSON文件
            String jsonContent = mapper.writeValueAsString(fileInfo);
            Files.write(Paths.get("/data/ossftp/config.json"), jsonContent.getBytes(), StandardOpenOption.CREATE);
            //重启服务
            HttpUtil.doGet("http://"+ftpHost+":"+ftpWebPort+"/restart");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public HttpResult pageOss(HttpServletRequest request, OssPage page) {
        String userId = tokenUtil.getUserId(request);
        UserFtp byUserId = ftpMapper.getByUserId(userId);
        if (null==byUserId){
            String language = request.getHeader("language");
            if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                return HttpResult.fail("FTP account not created");
            }
            return HttpResult.fail("未創建ftp賬號！");
        }

        if (StringUtils.isEmpty(page.getPrefix())) {
            page.setPrefix(AliOssUtil.CUSTOM+userId + "/ftp");
        }else{
            page.setPrefix(AliOssUtil.CUSTOM+userId + "/ftp/"+page.getPrefix());
        }
        return new HttpResult(AliOssUtil.pageOss(page));
    }

    @Override
    public HttpResult deleteFtp(HttpServletRequest request, PictureInfo pictureInfo) {
        String userId = tokenUtil.getUserId(request);
        String language = request.getHeader("language");
        if (pictureInfo.getPictureUrl().indexOf(userId)<0){
            if(StringUtils.isNotEmpty(language)&&language.equals("en")){
                return HttpResult.fail("You are not the owner of this image");
            }
            return HttpResult.fail("您不是該圖片擁有者");
        }
        AliOssUtil.delShopImage(pictureInfo.getPictureUrl());
        return HttpResult.OK;
    }



}
